(function($) {
	$.widget('mobile.tabbar', $.mobile.navbar, {
		_create : function() {
			// Set the theme before we call the prototype, which will
			// ensure buttonMarkup() correctly grabs the inheritied theme.
			// We default to the "a" swatch if none is found
			var theme = this.element.jqmData('theme') || "a";
			this.element.addClass('ui-footer ui-footer-fixed ui-bar-' + theme);

			// Make sure the page has padding added to it to account for the
			// fixed bar
			this.element.closest('[data-role="page"]').addClass(
					'ui-page-footer-fixed');

			// Call the NavBar _create prototype
			$.mobile.navbar.prototype._create.call(this);
		},

		// Set the active URL for the Tab Bar, and highlight that button on the
		// bar
		setActive : function(url) {
			// Sometimes the active state isn't properly cleared, so we reset it
			// ourselves
			this.element.find('a')
					.removeClass('ui-btn-active ui-state-persist');
			this.element.find('a[href="' + url + '"]').addClass(
					'ui-btn-active ui-state-persist');
		}
	});

	$(document).bind('pagecreate create', function(e) {
		return $(e.target).find(":jqmData(role='tabbar')").tabbar();
	});

	$(":jqmData(role='page')").live('pageshow', function(e) {
		// Grab the id of the page that's showing, and select it on the Tab Bar
		// on the page
		var tabBar, id = $(e.target).attr('id');

		tabBar = $.mobile.activePage.find(':jqmData(role="tabbar")');
		if (tabBar.length) {
			tabBar.tabbar('setActive', '#' + id);
		}
	});

	var attachEvents = function() {
		var hoverDelay = $.mobile.buttonMarkup.hoverDelay, hov, foc;

		$(document)
				.bind(
						{
							"vmousedown vmousecancel vmouseup vmouseover vmouseout focus blur scrollstart" : function(
									event) {
								var theme, $btn = $(closestEnabledButton(event.target)), evt = event.type;

								if ($btn.length) {
									theme = $btn.attr("data-" + $.mobile.ns
											+ "theme");

									if (evt === "vmousedown") {
										if ($.support.touch) {
											hov = setTimeout(
													function() {
														$btn
																.removeClass(
																		"ui-btn-up-"
																				+ theme)
																.addClass(
																		"ui-btn-down-"
																				+ theme);
													}, hoverDelay);
										} else {
											$btn.removeClass(
													"ui-btn-up-" + theme)
													.addClass(
															"ui-btn-down-"
																	+ theme);
										}
									} else if (evt === "vmousecancel"
											|| evt === "vmouseup") {
										$btn
												.removeClass(
														"ui-btn-down-" + theme)
												.addClass("ui-btn-up-" + theme);
									} else if (evt === "vmouseover"
											|| evt === "focus") {
										if ($.support.touch) {
											foc = setTimeout(
													function() {
														$btn
																.removeClass(
																		"ui-btn-up-"
																				+ theme)
																.addClass(
																		"ui-btn-hover-"
																				+ theme);
													}, hoverDelay);
										} else {
											$btn.removeClass(
													"ui-btn-up-" + theme)
													.addClass(
															"ui-btn-hover-"
																	+ theme);
										}
									} else if (evt === "vmouseout"
											|| evt === "blur"
											|| evt === "scrollstart") {
										$btn.removeClass(
												"ui-btn-hover-" + theme
														+ " ui-btn-down-"
														+ theme).addClass(
												"ui-btn-up-" + theme);
										if (hov) {
											clearTimeout(hov);
										}
										if (foc) {
											clearTimeout(foc);
										}
									}
								}
							},
							"focusin focus" : function(event) {
								$(closestEnabledButton(event.target)).addClass(
										$.mobile.focusClass);
							},
							"focusout blur" : function(event) {
								$(closestEnabledButton(event.target))
										.removeClass($.mobile.focusClass);
							}
						});

		attachEvents = null;
	};

	$.fn.buttonMarkup = function(options) {
		var $workingSet = this;

		// Enforce options to be of type string
		options = (options && ($.type(options) == "object")) ? options : {};
		for ( var i = 0; i < $workingSet.length; i++) {
			var el = $workingSet.eq(i), e = el[0], o = $
					.extend(
							{},
							$.fn.buttonMarkup.defaults,
							{
								icon : options.icon !== undefined ? options.icon
										: el.jqmData("icon"),
								iconpos : options.iconpos !== undefined ? options.iconpos
										: el.jqmData("iconpos"),
								theme : options.theme !== undefined ? options.theme
										: el.jqmData("theme")
												|| $.mobile.getInheritedTheme(
														el, "c"),
								inline : options.inline !== undefined ? options.inline
										: el.jqmData("inline"),
								shadow : options.shadow !== undefined ? options.shadow
										: el.jqmData("shadow"),
								corners : options.corners !== undefined ? options.corners
										: el.jqmData("corners"),
								iconshadow : options.iconshadow !== undefined ? options.iconshadow
										: el.jqmData("iconshadow"),
								iconsize : options.iconsize !== undefined ? options.iconsize
										: el.jqmData("iconsize"),
								mini : options.mini !== undefined ? options.mini
										: el.jqmData("mini")
							}, options),

			// Classes Defined
			innerClass = "ui-btn-inner", textClass = "ui-btn-text", buttonClass, iconClass,
			// Button inner markup
			buttonInner, buttonText, buttonIcon, buttonElements;

			$.each(o, function(key, value) {
				e.setAttribute("data-" + $.mobile.ns + key, value);
				el.jqmData(key, value);
			});

			// Check if this element is already enhanced
			buttonElements = $
					.data(
							((e.tagName === "INPUT" || e.tagName === "BUTTON") ? e.parentNode
									: e), "buttonElements");

			if (buttonElements) {
				e = buttonElements.outer;
				el = $(e);
				buttonInner = buttonElements.inner;
				buttonText = buttonElements.text;
				// We will recreate this icon below
				$(buttonElements.icon).remove();
				buttonElements.icon = null;
			} else {
				buttonInner = document.createElement(o.wrapperEls);
				buttonText = document.createElement(o.wrapperEls);
			}
			buttonIcon = o.icon ? document.createElement("span") : null;

			if (attachEvents && !buttonElements) {
				attachEvents();
			}

			// if not, try to find closest theme container
			if (!o.theme) {
				o.theme = $.mobile.getInheritedTheme(el, "c");
			}

			buttonClass = "ui-btn ui-btn-up-" + o.theme;
			buttonClass += o.inline ? " ui-btn-inline" : "";
			buttonClass += o.shadow ? " ui-shadow" : "";
			buttonClass += o.corners ? " ui-btn-corner-all" : "";

			if (o.mini !== undefined) {
				// Used to control styling in headers/footers, where buttons
				// default to `mini` style.
				buttonClass += o.mini ? " ui-mini" : " ui-fullsize";
			}

			if (o.inline !== undefined) {
				// Used to control styling in headers/footers, where buttons
				// default to `mini` style.
				buttonClass += o.inline === false ? " ui-btn-block"
						: " ui-btn-inline";
			}

			if (o.icon) {
				o.icon = "ui-icon-" + o.icon;
				o.iconpos = o.iconpos || "left";

				iconClass = "ui-icon " + o.icon;

				if (o.iconshadow) {
					iconClass += " ui-icon-shadow";
				}

				if (o.iconsize) {
					iconClass += " ui-iconsize-" + o.iconsize;
				}
			}

			if (o.iconpos) {
				buttonClass += " ui-btn-icon-" + o.iconpos;

				if (o.iconpos == "notext" && !el.attr("title")) {
					el.attr("title", el.getEncodedText());
				}
			}

			innerClass += o.corners ? " ui-btn-corner-all" : "";

			if (o.iconpos && o.iconpos === "notext" && !el.attr("title")) {
				el.attr("title", el.getEncodedText());
			}

			if (buttonElements) {
				el.removeClass(buttonElements.bcls || "");
			}
			el.removeClass("ui-link").addClass(buttonClass);

			buttonInner.className = innerClass;

			buttonText.className = textClass;
			if (!buttonElements) {
				buttonInner.appendChild(buttonText);
			}
			if (buttonIcon) {
				buttonIcon.className = iconClass;
				if (!(buttonElements && buttonElements.icon)) {
					buttonIcon.appendChild(document.createTextNode("\u00a0"));
					buttonInner.appendChild(buttonIcon);
				}
			}

			while (e.firstChild && !buttonElements) {
				buttonText.appendChild(e.firstChild);
			}

			if (!buttonElements) {
				e.appendChild(buttonInner);
			}

			// Assign a structure containing the elements of this button to the
			// elements of this button. This
			// will allow us to recognize this as an already-enhanced button in
			// future calls to buttonMarkup().
			buttonElements = {
				bcls : buttonClass,
				outer : e,
				inner : buttonInner,
				text : buttonText,
				icon : buttonIcon
			};

			$.data(e, 'buttonElements', buttonElements);
			$.data(buttonInner, 'buttonElements', buttonElements);
			$.data(buttonText, 'buttonElements', buttonElements);
			if (buttonIcon) {
				$.data(buttonIcon, 'buttonElements', buttonElements);
			}
		}

		return this;
	};

	$.fn.buttonMarkup.defaults = {
		corners : true,
		shadow : true,
		iconshadow : true,
		iconsize : 18,
		wrapperEls : "span"
	};

	function closestEnabledButton(element) {
		var cname;

		while (element) {
			// Note that we check for typeof className below because the element
			// we
			// handed could be in an SVG DOM where className on SVG elements is
			// defined to
			// be of a different type (SVGAnimatedString). We only operate on
			// HTML DOM
			// elements, so we look for plain "string".
			cname = (typeof element.className === 'string')
					&& (element.className + ' ');
			if (cname && cname.indexOf("ui-btn ") > -1
					&& cname.indexOf("ui-disabled ") < 0) {
				break;
			}

			element = element.parentNode;
		}

		return element;
	}

})(jQuery);
